package cn.hongwei.service.impl;

import cn.hongwei.config.SmsProperties;
import cn.hongwei.result.ResultCodeEnum;
import cn.hongwei.service.SmsService;
import cn.hongwei.service.base.consts.Keys;
import cn.hongwei.service.base.handler.GuliException;
import cn.hongwei.utils.FormUtils;
import cn.hongwei.utils.HttpUtils;
import cn.hongwei.utils.RandomUtils;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class SmsServiceImpl implements SmsService {
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    SmsProperties smsProperties;

    @Override
    public void sendMsg(String mobile) {
        //1、验证手机号码格式:正则表达式
        if(!FormUtils.isMobile(mobile)){
            throw new GuliException(ResultCodeEnum.LOGIN_PHONE_ERROR);
        }
        //2、验证手机号码发送短信的频率[第一次发送短信成功后再回来写频率校验]
        //一分钟只能发送一次   一天只能发送5次
        // 保存一分钟，以后该手机号码获取验证码时，可以判断下面的key是否存在
        String mobileCodePerMinKey = Keys.CODE_PER_MIN_KEY +mobile;
        if(redisTemplate.hasKey(mobileCodePerMinKey)){
            throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR_BUSINESS_LIMIT_CONTROL);
        }
        String mobileCodePerDayKey = Keys.CODE_PER_DAY_KEY+mobile;
        //判断该手机号码一天内获取验证码的次数是否超过5次
        Object countObj = redisTemplate.opsForValue().get(mobileCodePerDayKey);
        if(countObj!=null){
            if(Integer.parseInt(countObj.toString())>=5){
                throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR_COUNT_LIMIT_CONTROL);
            }
        }else{
            //如果countObj为空，代表该手机号码第一次来获取验证码
            redisTemplate.opsForValue().set(mobileCodePerDayKey , 0 , 24 , TimeUnit.HOURS);
        }

        //3、生成验证码：
        String fourBitRandom = RandomUtils.getFourBitRandom();
        //4、发送验证码
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + smsProperties.getAppcode());
        Map<String, String> querys = new HashMap<String, String>();
        querys.put("mobile", mobile);
        querys.put("param", "**code**:"+fourBitRandom+",**minute**:"+ Keys.CODE_EXPIRE_MINUTE);
        querys.put("smsSignId", smsProperties.getSmsSignId());
        querys.put("templateId", smsProperties.getTemplateId());
        Map<String, String> bodys = new HashMap<String, String>();
        try {
            HttpResponse response = HttpUtils.doPost(smsProperties.getHost(),
                    smsProperties.getPath(), smsProperties.getMethod(),
                    headers, querys, bodys);
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            //判断短信发送成功还是失败
            Gson gson = new Gson();
            Map map = gson.fromJson(result, Map.class);
            String resultCode = map.get("code").toString();
            if(!"0".equals(resultCode)){
                throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR);
            }
            //短信发送成功
            //5、后端缓存验证码
            //拼接当前手机号码唯一的key
            String mobileCodeKey = Keys.CODE_CODE_KEY + mobile;
            redisTemplate.opsForValue().set( mobileCodeKey,fourBitRandom,Keys.CODE_EXPIRE_MINUTE, TimeUnit.MINUTES);
            //6、更新用户获取验证码的频率
            redisTemplate.opsForValue().set(mobileCodePerMinKey ,mobileCodePerMinKey, 1 , TimeUnit.MINUTES);
            //更新手机号码今天获取验证码的次数
            // incr key;  如果key不存在，默认值为0，加完之后变为1  ，如果key存在且是数字，自增1
            redisTemplate.opsForValue().increment(mobileCodePerDayKey);

        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
            throw new GuliException(ResultCodeEnum.SMS_SEND_ERROR);
        }



    }
}
